package pers.cj.pdos.controller;


import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.metadata.Sheet;
import com.alibaba.excel.support.ExcelTypeEnum;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import pers.cj.pdos.controller.base.BaseController;
import pers.cj.pdos.controller.entity.ResponseData;
import pers.cj.pdos.controller.entity.ResponseEntity;
import pers.cj.pdos.controller.entity.ResponseList;
import pers.cj.pdos.entity.*;
import pers.cj.pdos.excel.ExcelBorrowIn;
import pers.cj.pdos.excel.ExcelInGoods;
import pers.cj.pdos.service.*;
import pers.cj.pdos.task.CleanTempExcelTask;
import pers.cj.pdos.utils.*;
import pers.cj.pdos.vo.*;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.util.*;

/**
 * <p>
 * 借入单后处于待入库状态，归还状态为未归还状态，等进行进货或者归还后，则规范状态为已归还。 前端控制器
 * </p>
 *
 * @author chenj
 * @since 2019-11-04
 */
@Controller
@RequestMapping("/house")
public class BorrowInController extends BaseController {
    @Autowired
    IBorrowInService borrowInService;
    @Autowired
    IHouseInService houseInService;
    @Autowired
    IInGoodsService inGoodsService;
    @Autowired
    IBorrowInBackService borrowInBackService;
    @Autowired
    IHouseInGoodsService houseInGoodsService;

    @RequiresPermissions("borrowIn:query")
    @RequestMapping("/borrowIn")
    public String borrowIn(){
        return "borrowIn/borrowIn";
    }


    @RequiresPermissions("borrowIn:insert")
    @RequestMapping("/borrowInNew")
    public String borrowInNew(){
        return "borrowIn/borrowInNew";
    }

    @RequiresPermissions("borrowIn:query")
    @RequestMapping("/borrowInDetail")
    public String borrowInDetail(Model model, String id){
        model.addAttribute("id",id);
        return "borrowIn/borrowInDetail";
    }

    @ResponseBody
    @RequiresPermissions("borrowIn:query")
    @RequestMapping("/borrowIn/getList")
    public ResponseList getList(int page,
                                int limit,
                                String close,
                                String search,
                                String no,
                                String goodsName,
                                String remark,
                                String provider,
                                String date1,
                                String date2,
                                String storeId,
                                String userId,
                                String makeTime1,
                                String makeTime2,
                                String houseId,
                                String makeUserId,
                                String inStatus){
        Company company = getCompany();
        UserVo userVo = getLoginUserVo();

        List<BorrowInVo> list = borrowInService.listVo(company.getId(),
                page,
                limit,
                Utils.genBoolean(close),
                Utils.genLikeData(search),
                Utils.genLikeData(no),
                Utils.genLikeData(goodsName),
                Utils.genLikeData(remark),
                Utils.genLikeData(provider),
                Utils.genDate(makeTime1),
                Utils.genDate(makeTime2),
                storeId,
                PdosUtils.getViewOrderStoreId(userVo,null),
                PdosUtils.getViewOrderUserId(userVo,userId),
                Utils.genDate(date1),
                Utils.genDate(date2),
                houseId,
                makeUserId,
                Utils.genInteger(inStatus));
        long count = borrowInService.count(company.getId(),
                Utils.genBoolean(close),
                Utils.genLikeData(search),
                Utils.genLikeData(no),
                Utils.genLikeData(goodsName),
                Utils.genLikeData(remark),
                Utils.genLikeData(provider),
                Utils.genDate(makeTime1),
                Utils.genDate(makeTime2),
                storeId,
                PdosUtils.getViewOrderStoreId(userVo,null),
                PdosUtils.getViewOrderUserId(userVo,userId),
                Utils.genDate(date1),
                Utils.genDate(date2),
                houseId,
                makeUserId,
                Utils.genInteger(inStatus));
        return ResponseList.success(count,list);
    }

    @ResponseBody
    @RequiresPermissions("borrowIn:insert")
    @RequestMapping("/borrowIn/add")
    public ResponseEntity add(@RequestBody BorrowInVo borrowInVo){

        Company company = getCompany();
        BusinessSet businessSet = getBusinessSet();

        if (Utils.isEmpty(borrowInVo.getNo())){
            return ResponseEntity.fail("编号不能为空");
        }

        if (Utils.isEmpty(borrowInVo.getBorrowInGoodsVoList())){
            return ResponseEntity.fail("请选择任何商品");
        }

        if (borrowInVo.getDate() == null){
            return ResponseEntity.fail("业务日期不能为空");
        }

        if (borrowInVo.getBackDate() == null){
            return ResponseEntity.fail("预计归还日期不能为空");
        }

        if (borrowInService.checkNo(borrowInVo.getNo(),company.getId())){
            return ResponseEntity.fail("编号已被使用");
        }

        if (getHouseLocking(borrowInVo.getHouseId())) {
            return ResponseEntity.fail("仓库被锁定，请更换仓库");
        }


        BorrowIn borrowIn = DataUtil.genEntityFromVo(BorrowIn.class,borrowInVo);
        DataUtil.processEntity(company,borrowIn);
        borrowIn.setClose(false);
        borrowIn.setInStatus(1);
        borrowIn.setMakeUserId(getLoginUserId());
        borrowIn.setMakeTime(borrowIn.getTime());
        if (!PdosUtils.houseInOut(businessSet)) {
            borrowIn.setStatus(1);
        } else {
            borrowIn.setStatus(2);
        }


        List<BorrowInGoods> borrowInGoodsList = new ArrayList<>();
        List<GoodsSn> goodsSnList = new ArrayList<>();
        List<GoodsSnLog> goodsSnLogList = new ArrayList<>();
        Map<String,Object> snInitMap = new HashMap<>();
        snInitMap.put("inDate", new Date());//设置入库日期
        snInitMap.put("status", 1);//设置状态为未出库
        for (BorrowInGoodsVo vo:borrowInVo.getBorrowInGoodsVoList()) {
            BorrowInGoods entity = DataUtil.genEntityFromVo(BorrowInGoods.class, vo);
            DataUtil.processEntity(company,entity);
            entity.setBorrowInId(borrowIn.getId());
            entity.setHasNumber(new BigDecimal(0));
            entity.setInGoodsNumber(new BigDecimal(0));
            entity.setWaitNumber(vo.getNumber());
            borrowInGoodsList.add(entity);

            if (!Utils.isEmpty(vo.getGoodsSnList())){
                for (GoodsSn goodsSn : vo.getGoodsSnList()) {
                    DataUtil.processEntity(company, goodsSn,snInitMap);
                    goodsSnList.add(goodsSn);

                    GoodsSnLog log = new GoodsSnLog();
                    DataUtil.processEntity(company,log);
                    log.setGoodsId(goodsSn.getGoodsId());
                    log.setSn(goodsSn.getSn());
                    log.setType(12);
                    log.setBorrowInGoodsId(entity.getId());
                    goodsSnLogList.add(log);
                }
            }
        }



        borrowInService.insert(businessSet, borrowIn,borrowInGoodsList, goodsSnList,goodsSnLogList);

        if (!Utils.isEmpty(goodsSnList) && PdosUtils.houseInOut(businessSet)) {
            //已启用待出库入管理，但是前台传入了sn号，提示
            return ResponseEntity.success("处理成功，管理员在您新增单据过程中启用了出入库管理，录入的sn需要在入库时录入");
        }
        return ResponseEntity.success();
    }

    @ResponseBody
    @RequiresPermissions("borrowIn:close")
    @RequestMapping("/borrowIn/close")
    public ResponseEntity close(@RequestBody BorrowIn borrowIn){
        //检查是否已经关闭
        if (borrowInService.checkClose(borrowIn)){
            return ResponseEntity.fail("该单据已被关闭，不能重复关闭");
        }


        if(inGoodsService.count(new QueryWrapper<InGoods>().eq("close",false).eq("borrow_in_id", borrowIn.getId())) > 0) {
            return ResponseEntity.fail("该借入单已产生进货单，无法作废。");
        }

        if(borrowInBackService.count(new QueryWrapper<BorrowInBack>().eq("close",false).eq("borrow_in_id", borrowIn.getId())) > 0) {
            return ResponseEntity.fail("该借入单已产生归还单，无法作废。");
        }

        if(houseInService.checkByLinkId(borrowIn.getId())) {
            return ResponseEntity.fail("该订单存在入库单，请先作废对应的入库单");
        }

        try {
            borrowInService.close(borrowIn, getBusinessSet());
            return ResponseEntity.success();
        }catch (Exception e) {
            return ResponseEntity.fail("关闭订单失败");
        }
    }


    @ResponseBody
    @RequestMapping("/borrowIn/getVoById")
    public ResponseData getVoById(String id) {
        return ResponseData.success(borrowInService.getVoById(id));
    }

    @ResponseBody
    @RequestMapping("/borrowIn/getVoByIdWithCanTransfer")
    public ResponseData getVoByIdWithCanTransfer(String id) {
        BorrowInVo borrowInVo = borrowInService.getVoById(id);
        if (borrowInVo == null) {
            return ResponseData.fail("未找到单据");
        }


        //获取到此进货单的已经入库的数量
        if (borrowInVo.getStatus() != 1) {
            //由入库单入库的，需要取得该进货的每个商品的入库数量
            List<HouseInGoods> houseInGoodsList = houseInGoodsService.listByLinkId(id);
            Map<String, BigDecimal> houseInMap = new HashMap<>();//key-goodsId value-number
            for (HouseInGoods houseInGoods : houseInGoodsList) {
                String borrowInGoodsId = houseInGoods.getBorrowInGoodsId();
                BigDecimal number = houseInGoods.getNumber();
                if (houseInMap.containsKey(borrowInGoodsId)) {
                    //若存在，则累加数量
                    houseInMap.put(borrowInGoodsId, houseInMap.get(borrowInGoodsId).add(number));
                } else {
                    //不存在，则新建
                    houseInMap.put(borrowInGoodsId, number);
                }
            }

            //新组成的数据
            BigDecimal zero = new BigDecimal(0);
            List<BorrowInGoodsVo> borrowInGoodsVoList = new ArrayList<>();
            for (BorrowInGoodsVo vo : borrowInVo.getBorrowInGoodsVoList()) {
                //已出库，且还有待转数量的商品
                if (houseInMap.containsKey(vo.getId()) && vo.getWaitNumber().compareTo(zero)==1) {
                    //将已存在进货单对应入库单的商品添加到新表，并将数量重新赋值
                    if (houseInMap.get(vo.getId()).compareTo(vo.getWaitNumber()) == -1) {
                        vo.setWaitNumber(houseInMap.get(vo.getId()));
                    }
                    vo.setNumber(vo.getWaitNumber());
                    vo.setAmount(vo.getNumber().multiply(vo.getPrice()));//重新计算器总额
                    borrowInGoodsVoList.add(vo);
                }
            }
            borrowInVo.setBorrowInGoodsVoList(borrowInGoodsVoList);
        }

        return ResponseData.success(borrowInVo);
    }

    /**
     * 先更具请求数据
     * @throws IOException
     */
    @ResponseBody
    @RequiresPermissions("borrowIn:export")
    @RequestMapping("/borrowIn/export")
    public ResponseData export(String close,
                               String search,
                               String no,
                               String goodsName,
                               String remark,
                               String provider,
                               String date1,
                               String date2,
                               String storeId,
                               String userId,
                               String makeTime1,
                               String makeTime2,
                               String houseId,
                               String makeUserId,
                               String inStatus){
        Company company = getCompany();
        UserVo userVo = getLoginUserVo();

        List<BorrowInVo> list = borrowInService.listVo(company.getId(),
                null,
                null,
                Utils.genBoolean(close),
                Utils.genLikeData(search),
                Utils.genLikeData(no),
                Utils.genLikeData(goodsName),
                Utils.genLikeData(remark),
                Utils.genLikeData(provider),
                Utils.genDate(makeTime1),
                Utils.genDate(makeTime2),
                storeId,
                PdosUtils.getViewOrderStoreId(userVo,null),
                PdosUtils.getViewOrderUserId(userVo,userId),
                Utils.genDate(date1),
                Utils.genDate(date2),
                houseId,
                makeUserId,
                Utils.genInteger(inStatus));

        String fileName = "借入单列表" + DateUtils.getDate(new Date(), DateUtils.YYYYMMDDHHMMSSSS) + ".xlsx";
        try {
            String path = FileProperUtil.getInstance().getVal("excel.temp");
            OutputStream out = new FileOutputStream(path+fileName);
            ExcelWriter writer = new ExcelWriter(out, ExcelTypeEnum.XLSX,true);
            Sheet sheet1 = new Sheet(1,0, ExcelBorrowIn.class);
            sheet1.setSheetName("借入单信息");
            writer.write(genExcelList(list), sheet1);
            writer.finish();
            out.close();
            CleanTempExcelTask.put(fileName,new Date().getTime());
            return ResponseData.success(fileName);
        } catch (IOException e) {
            return ResponseData.fail("订单列表导出失败");
        }
    }

    private List<ExcelBorrowIn> genExcelList(List<BorrowInVo> borrowInVoList) {
        List<ExcelBorrowIn> list = new ArrayList<>();
        for (BorrowInVo vo : borrowInVoList){
            ExcelBorrowIn excel = new ExcelBorrowIn();
            excel.setDate(DateUtils.getDate(vo.getDate(), DateUtils.YYYY_MM_DD));
            excel.setNo(vo.getNo());

            excel.setProviderNo(vo.getProvider().getNo());
            excel.setProvider(vo.getProvider().getName());
            String goods = "";
            for (BorrowInGoodsVo borrowInGoodsVo : vo.getBorrowInGoodsVoList()){
                goods += borrowInGoodsVo.getGoodsVo().getName() + "、";
            }
            excel.setGoods(goods);
            excel.setBackDate(DateUtils.getDate(vo.getBackDate(), DateUtils.YYYY_MM_DD));
            excel.setStore(vo.getHouseVo().getStore().getName());
            excel.setHouse(vo.getHouseVo().getName());
            if (vo.getInStatus() == 1){
                excel.setInStatus("未归还");
            } else if (vo.getInStatus() == 2){
                excel.setInStatus("部分归还");
            } else {
                excel.setInStatus("全部归还");
            }

            excel.setUser(vo.getUser().getName());
            excel.setMakeUser(vo.getMakeUser().getName());
            excel.setRemark(vo.getRemark());
            excel.setClose(vo.getClose() ? "是":"否");
            list.add(excel);
        }
        return list;
    }
}
